package cc.fs.zhihuapp.utils;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;

import org.videolan.libvlc.EventHandler;
import org.videolan.libvlc.IVideoPlayer;
import org.videolan.libvlc.LibVLC;
import org.videolan.vlc.util.WeakHandler;

import java.util.Timer;
import java.util.TimerTask;

import cc.fs.zhihuapp.ui.activity.demo.PlayerView;


/**
 * Created by fostion on 2015/11/18.
 */
public class VlcPlayer implements IVideoPlayer{

    private final String TAG = "--VlcPLayer--";
    private String url;
    private LibVLC player;
    private SurfaceView mSurfaceVidew;
    private SurfaceHolder mSurfaceHodler;
    private Context context;

    private int screenWidth;
    private int screenHeight;

    private boolean isUpdate = true;
    //监听变化
    private PlayerListener playerListener;

    public void e(String msg){
        Log.e(TAG,msg);
    }

    /*******************************************************
     * 通过定时器获取时间
     ******************************************************/
    private Timer timer;
    private TimerTask mTimerTask = new TimerTask() {
        @Override
        public void run() {
            if (player == null || !isUpdate)
                return;
            if (isPlaying()) {
                int position = ((Number)getCurrentTime()).intValue();
                int duration = ((Number)getDuration()).intValue();

                if(playerListener != null) {
                    playerListener.onProgress(duration, position);
                }
            } else {
                if(playerListener != null){
                    playerListener.onBuffering();
                }
            }
        }
    };

    /**
     * 初始化vlc-lib
     */
    public VlcPlayer(Context _context){
        this.context = _context;
        try {
            player = LibVLC.getExistingInstance();
            if (player == null) {
                player = LibVLC.getInstance();
                player.init(context);
                timer = new Timer();
            }
        } catch (Exception e) {
           e("-初始化失败-");
        }
    }

    public void playUrl(String url){
        if(player != null && url != null){
            player.eventVideoPlayerActivityCreated(true);
            player.playMRL(url);
            mSurfaceHodler.setKeepScreenOn(true);
            timer.schedule(mTimerTask,0,500);
        }
    }

    /**
     * 设置画面显示的surfaceholder
     */
    public void setSurfaceHolder(SurfaceView surfaceView){
        this.mSurfaceVidew = surfaceView;
        this.mSurfaceHodler = mSurfaceVidew.getHolder();
        if(player != null && mSurfaceVidew != null) {
            player.attachSurface(mSurfaceHodler.getSurface(), this);
        }
    }

    /**
     * 结束时清除surfaceholder
     */
    public void destorySurfaceHolder(){
        if(player != null){
            player.detachSurface();
        }
    }
    private int mVideoHeight;
    private int mVideoWidth;
    private int mVideoVisibleHeight;
    private int mVideoVisibleWidth;
    private int mSarNum;
    private int mSarDen;

    private static final int HANDLER_BUFFER_START = 1;
    private static final int HANDLER_BUFFER_END = 2;
    private static final int HANDLER_SURFACE_SIZE = 3;

    private static final int SURFACE_BEST_FIT = 0;
    private static final int SURFACE_FIT_HORIZONTAL = 1;
    private static final int SURFACE_FIT_VERTICAL = 2;
    private static final int SURFACE_FILL = 3;
    private static final int SURFACE_16_9 = 4;
    private static final int SURFACE_4_3 = 5;
    private static final int SURFACE_ORIGINAL = 6;
    private int mCurrentSize = SURFACE_BEST_FIT;
    /**
     *将视频画面显示出来
     * @param width Frame width
     * @param height Frame height
     * @param visible_width Visible frame width
     * @param visible_height Visible frame height
     * @param sar_num Surface aspect ratio numerator
     * @param sar_den Surface aspect ratio denominator
     */
    @Override
    public void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den) {
        if (width * height == 0) {
            return;
        }
        mVideoHeight = height;
        mVideoWidth = width;
        mVideoVisibleHeight = visible_height;
        mVideoVisibleWidth = visible_width;
        mSarNum = sar_num;
        mSarDen = sar_den;
        mHandler.removeMessages(HANDLER_SURFACE_SIZE);
        mHandler.sendEmptyMessage(HANDLER_SURFACE_SIZE);
    }

    public long getCurrentTime(){
        if(player != null){
            return player.getTime();
        }
        return 0;
    }

    public long getDuration(){
        if(player != null){
            return player.getLength();
        }
        return 0;
    }

    public boolean isPlaying(){
        if(player != null){
            return player.isPlaying();
        }
        return false;
    }

    public void pause(){
        if(player != null){
            player.pause();
            mSurfaceHodler.setKeepScreenOn(false);
            isUpdate = false;
        }
    }

    public void play(){
        if(player != null){
            player.play();
            mSurfaceHodler.setKeepScreenOn(true);
            isUpdate = true;
        }
    }

    public void setUpdate(boolean isUpdate){
        this.isUpdate = isUpdate;
    }

    public void relase(){
        if(player != null){
            e("结束播放释放资源");
            isUpdate = false;
            timer.cancel();
            player.stop();
            player.destroy();
            if(mSurfaceHodler != null)
               mSurfaceHodler.setKeepScreenOn(false);
        }
    }

    public void setNetWorkCache(int time) {
        if(player != null)
           player.setNetworkCaching(time);
    }

    public void seekTo(int position){
        if(player == null || player.getLength() <= 0)
            return;
        int cTime = position;
        int nTime =  ((Number) getCurrentTime()).intValue();
        long offsetTime = getCurrentTime() + cTime - nTime;
        if (offsetTime < 0)
            offsetTime = 0;
        player.setTime(offsetTime);
    }

    public void seekBack(){
        if(isPlaying()){
            long position = getCurrentTime() - 20000;
            player.setTime(position);
        }
    }

    public void seekForward(){
        if(isPlaying()){
            long position = getCurrentTime() + 20000;
            player.setTime(position);
        }
    }

    private Handler mHandler = new Handler(){
        @Override
        public void dispatchMessage(Message msg) {
            switch (msg.what){
                case HANDLER_SURFACE_SIZE:
                    changeSurfaceSize();
                    break;
            }
        }
    };

    public void setScreenWidth(int width){
        screenWidth = width;
    }

    public void setScreenHeight(int height){
        screenHeight = height;
    }

    private void changeSurfaceSize() {
        // get screen size
        int sw =  screenWidth;
        int sh = screenHeight;
        double dw = sw, dh = sh;
        boolean isPortrait;
        isPortrait = true;
        if (sw > sh && isPortrait || sw < sh && !isPortrait) {
            dw = sh;
            dh = sw;
        }
        // sanity check
        if (dw * dh == 0 || mVideoWidth * mVideoHeight == 0) {
            Log.e(TAG, "Invalid surface size");
            return;
        }
        // compute the aspect ratio
        double ar, vw;
        if (mSarDen == mSarNum) {
			/* No indication about the density, assuming 1:1 */
            vw = mVideoVisibleWidth;
            ar = (double) mVideoVisibleWidth / (double) mVideoVisibleHeight;
        } else {
			/* Use the specified aspect ratio */
            vw = mVideoVisibleWidth * (double) mSarNum / mSarDen;
            ar = vw / mVideoVisibleHeight;
        }

        // compute the display aspect ratio
        double dar = dw / dh;

        switch (mCurrentSize) {
            case SURFACE_BEST_FIT:
                if (dar < ar)
                    dh = dw / ar;
                else
                    dw = dh * ar;
                break;
            case SURFACE_FIT_HORIZONTAL:
                dh = dw / ar;
                break;
            case SURFACE_FIT_VERTICAL:
                dw = dh * ar;
                break;
            case SURFACE_FILL:
                break;
            case SURFACE_16_9:
                ar = 16.0 / 9.0;
                if (dar < ar)
                    dh = dw / ar;
                else
                    dw = dh * ar;
                break;
            case SURFACE_4_3:
                ar = 4.0 / 3.0;
                if (dar < ar)
                    dh = dw / ar;
                else
                    dw = dh * ar;
                break;
            case SURFACE_ORIGINAL:
                dh = mVideoVisibleHeight;
                dw = vw;
                break;
        }

        mSurfaceHodler.setFixedSize(mVideoWidth, mVideoHeight);
        ViewGroup.LayoutParams lp = mSurfaceVidew.getLayoutParams();
        lp.width = (int) Math.floor(screenHeight*2);
        lp.height = (int) Math.floor(screenWidth*2);
        mSurfaceVidew.setLayoutParams(lp);
        mSurfaceVidew.invalidate();
    }

    public void setPlayerListener(PlayerListener playerListener) {
        this.playerListener = playerListener;
    }

    public interface PlayerListener{
        void onPrepared();
        void onBuffering();
        void onBuffered(float buffered);
        void onProgress(int total, int progress);
        void onCompletion();
    }

    private final Handler eventHandler = new VlcPlayerHandler(this);

    private static class VlcPlayerHandler extends WeakHandler<VlcPlayer>{

        public VlcPlayerHandler(VlcPlayer owner) {
            super(owner);
        }

        /**
         * 处理播放器播放视频时的各种状态
         */
        @Override
        public void handleMessage(Message msg) {
            String TAG = " -VlcPlayerHandler- ";
            VlcPlayer player = getOwner();
            if(player == null)
                return;
            switch (msg.getData().getInt("event")){
                case EventHandler.MediaPlayerNothingSpecial:
                    break;
                case EventHandler.MediaPlayerOpening:
                    break;
                case EventHandler.MediaParsedChanged:
                    Log.d(TAG, "MediaParsedChanged");
                    break;
                case EventHandler.MediaPlayerPlaying://正在播放
                    Log.d(TAG, "MediaPlayerPlaying");
                    if (player.playerListener != null) {
                        player.playerListener.onBuffering();
                    }
                    break;
                case EventHandler.MediaPlayerPaused://暂停播放
                    Log.d(TAG, "MediaPlayerPaused");
                    break;
                case EventHandler.MediaPlayerStopped://停止播放
                    Log.d(TAG, "MediaPlayerStopped");
                    break;
                case EventHandler.MediaPlayerEndReached://播放完毕
                    Log.d(TAG, "MediaPlayerEndReached");
//                    if (player.mOnChangeListener != null) {
//                        player.mOnChangeListener.onEnd();
//                    }
                    break;
                case EventHandler.MediaPlayerVout:
                    break;
                case EventHandler.MediaPlayerPositionChanged://可拉动播放
//                    if (!player.mCanSeek) {
//                        player.mCanSeek = true;
//                    }
                    break;
                case EventHandler.MediaPlayerEncounteredError://解码失败
                    Log.d(TAG, "MediaPlayerEncounteredError");
//                    if (player.mOnChangeListener != null) {
//                        player.mOnChangeListener.onError();
//                    }
                    break;
                case EventHandler.HardwareAccelerationError:
                    Log.d(TAG, "HardwareAccelerationError");//硬件加速失败
//                    if (player.mOnChangeListener != null && playerView.mDisabledHardwareAcceleration) {
//                        player.stop();
//                        player.mOnChangeListener.onError();
//                    } else {
//                        player.handleHardwareAccelerationError();
//                    }
                    break;
                case EventHandler.MediaPlayerTimeChanged:
                    // avoid useless error logs
                    break;
                case EventHandler.MediaPlayerBuffering:
                    Log.d(TAG, "MediaPlayerBuffering");
                    if (player.playerListener != null) {
                        player.playerListener.onBuffered(msg.getData().getFloat("data"));
                    }
                    break;
                default:
                    Log.d(TAG, String.format("Event not handled (0x%x)", msg.getData().getInt("event")));
                    break;
            }
        }
    }

}
